package ltd.newbee.mall.service.impl;

import ltd.newbee.mall.dao.MenuMapper;
import ltd.newbee.mall.entity.Menu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.stream.Collectors;

@Service
public class MenuService {

    @Autowired
    private MenuMapper menuMapper;

    /**
     * 根据用户ID获取菜单树
     */
    public List<Menu> getMenuTreeByUserId(Long userId) {
        List<Menu> menus = menuMapper.selectMenusByUserId(userId);
        return buildMenuTree(menus);
    }

    /**
     * 获取所有菜单树
     */
    public List<Menu> getAllMenuTree() {
        List<Menu> menus = menuMapper.selectAllMenus();
        return buildMenuTree(menus);
    }

    /**
     * 根据角色ID获取菜单树
     */
    public List<Menu> getMenuTreeByRoleId(Long roleId) {
        List<Menu> menus = menuMapper.selectMenusByRoleId(roleId);
        return buildMenuTree(menus);
    }

    /**
     * 获取角色拥有的菜单ID列表
     */
    public List<Long> getMenuIdsByRoleId(Long roleId) {
        List<Menu> menus = menuMapper.selectMenusByRoleId(roleId);
        return menus.stream()
                .map(Menu::getMenuId)
                .collect(Collectors.toList());
    }

    /**
     * 构建菜单树
     */
    private List<Menu> buildMenuTree(List<Menu> menus) {
        if (menus == null || menus.isEmpty()) {
            return new ArrayList<>();
        }

        Map<Long, Menu> menuMap = new HashMap<>();
        List<Menu> rootMenus = new ArrayList<>();

        // 将所有菜单放入map
        for (Menu menu : menus) {
            menuMap.put(menu.getMenuId(), menu);
        }

        // 构建树形结构
        for (Menu menu : menus) {
            if (menu.getParentId() == null || menu.getParentId() == 0) {
                rootMenus.add(menu);
            } else {
                Menu parent = menuMap.get(menu.getParentId());
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(menu);
                }
            }
        }

        // 排序
        rootMenus.sort(Comparator.comparing(Menu::getMenuSort));
        sortMenuTree(rootMenus);

        return rootMenus;
    }

    /**
     * 递归排序菜单树
     */
    private void sortMenuTree(List<Menu> menus) {
        if (menus == null || menus.isEmpty()) {
            return;
        }

        for (Menu menu : menus) {
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                menu.getChildren().sort(Comparator.comparing(Menu::getMenuSort));
                sortMenuTree(menu.getChildren());
            }
        }
    }

    /**
     * 新增菜单
     */
    @Transactional
    public boolean addMenu(Menu menu) {
        // 验证必要字段
        if (!StringUtils.hasText(menu.getMenuName())) {
            throw new RuntimeException("菜单名称不能为空");
        }

        // 设置默认值
        if (menu.getParentId() == null) {
            menu.setParentId(0L);
        }
        if (menu.getMenuSort() == null) {
            menu.setMenuSort(0);
        }
        if (menu.getIsVisible() == null) {
            menu.setIsVisible(1);
        }

        // 检查菜单路径是否重复
        if (StringUtils.hasText(menu.getMenuPath())) {
            Menu existingMenu = menuMapper.selectMenuByPath(menu.getMenuPath());
            if (existingMenu != null) {
                throw new RuntimeException("菜单路径已存在");
            }
        }

        return menuMapper.insertMenu(menu) > 0;
    }

    /**
     * 更新菜单
     */
    @Transactional
    public boolean updateMenu(Menu menu) {
        if (menu.getMenuId() == null) {
            throw new RuntimeException("菜单ID不能为空");
        }

        // 验证菜单是否存在
        Menu existingMenu = menuMapper.selectMenuById(menu.getMenuId());
        if (existingMenu == null) {
            throw new RuntimeException("菜单不存在");
        }

        // 检查菜单路径是否重复（排除自身）
        if (StringUtils.hasText(menu.getMenuPath())) {
            Menu pathMenu = menuMapper.selectMenuByPath(menu.getMenuPath());
            if (pathMenu != null && !pathMenu.getMenuId().equals(menu.getMenuId())) {
                throw new RuntimeException("菜单路径已存在");
            }
        }

        // 防止将父菜单设置为自己或子菜单
        if (menu.getParentId() != null && menu.getParentId().equals(menu.getMenuId())) {
            throw new RuntimeException("父菜单不能是自己");
        }

        // 检查是否形成循环依赖
        if (menu.getParentId() != null && menu.getParentId() != 0) {
            checkCircularDependency(menu.getMenuId(), menu.getParentId());
        }

        return menuMapper.updateMenu(menu) > 0;
    }

    /**
     * 检查循环依赖
     */
    private void checkCircularDependency(Long menuId, Long parentId) {
        Set<Long> visited = new HashSet<>();
        visited.add(menuId);

        Long currentParentId = parentId;
        while (currentParentId != null && currentParentId != 0) {
            if (visited.contains(currentParentId)) {
                throw new RuntimeException("检测到循环依赖，无法设置父菜单");
            }
            visited.add(currentParentId);

            Menu parentMenu = menuMapper.selectMenuById(currentParentId);
            if (parentMenu == null) {
                break;
            }
            currentParentId = parentMenu.getParentId();
        }
    }

    /**
     * 删除菜单
     */
    @Transactional
    public boolean deleteMenu(Long menuId) {
        if (menuId == null) {
            throw new RuntimeException("菜单ID不能为空");
        }

        // 检查菜单是否存在
        Menu menu = menuMapper.selectMenuById(menuId);
        if (menu == null) {
            throw new RuntimeException("菜单不存在");
        }

        // 检查是否有子菜单
        int childCount = menuMapper.selectChildMenuCount(menuId);
        if (childCount > 0) {
            throw new RuntimeException("存在子菜单，无法删除");
        }

        // 删除角色菜单关联
        menuMapper.deleteRoleMenuByMenuId(menuId);

        return menuMapper.deleteMenu(menuId) > 0;
    }

    /**
     * 批量删除菜单
     */
    @Transactional
    public boolean batchDeleteMenus(List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            throw new RuntimeException("菜单ID列表不能为空");
        }

        for (Long menuId : menuIds) {
            // 检查是否有子菜单
            int childCount = menuMapper.selectChildMenuCount(menuId);
            if (childCount > 0) {
                throw new RuntimeException("菜单ID " + menuId + " 存在子菜单，无法删除");
            }
        }

        // 批量删除角色菜单关联
        for (Long menuId : menuIds) {
            menuMapper.deleteRoleMenuByMenuId(menuId);
        }

        // 批量删除菜单
        int result = 0;
        for (Long menuId : menuIds) {
            result += menuMapper.deleteMenu(menuId);
        }

        return result == menuIds.size();
    }

    /**
     * 更新角色菜单权限
     */
    @Transactional
    public boolean updateRoleMenus(Long roleId, List<Long> menuIds) {
        if (roleId == null) {
            throw new RuntimeException("角色ID不能为空");
        }

        // 删除原有权限
        menuMapper.deleteRoleMenuByRoleId(roleId);

        // 添加新权限
        if (menuIds != null && !menuIds.isEmpty()) {
            // 验证菜单是否存在
            for (Long menuId : menuIds) {
                Menu menu = menuMapper.selectMenuById(menuId);
                if (menu == null) {
                    throw new RuntimeException("菜单ID " + menuId + " 不存在");
                }
            }
            menuMapper.batchInsertRoleMenu(roleId, menuIds);
        }

        return true;
    }

    /**
     * 根据路径获取菜单
     */
    public Menu getMenuByPath(String path) {
        if (!StringUtils.hasText(path)) {
            return null;
        }
        return menuMapper.selectMenuByPath(path);
    }

    /**
     * 根据ID获取菜单
     */
    public Menu getMenuById(Long menuId) {
        if (menuId == null) {
            return null;
        }
        return menuMapper.selectMenuById(menuId);
    }

    /**
     * 获取所有菜单（平铺结构）
     */
    public List<Menu> getAllMenus() {
        return menuMapper.selectAllMenus();
    }

    /**
     * 根据父菜单ID获取子菜单
     */
    public List<Menu> getChildMenus(Long parentId) {
        List<Menu> allMenus = menuMapper.selectAllMenus();
        return allMenus.stream()
                .filter(menu -> Objects.equals(menu.getParentId(), parentId))
                .sorted(Comparator.comparing(Menu::getMenuSort))
                .collect(Collectors.toList());
    }

    /**
     * 搜索菜单
     */
    public List<Menu> searchMenus(String keyword) {
        List<Menu> allMenus = menuMapper.selectAllMenus();
        if (!StringUtils.hasText(keyword)) {
            return allMenus;
        }

        return allMenus.stream()
                .filter(menu -> menu.getMenuName().contains(keyword) ||
                        (menu.getMenuPath() != null && menu.getMenuPath().contains(keyword)))
                .collect(Collectors.toList());
    }

    /**
     * 获取菜单路径（面包屑）
     */
    public List<Menu> getMenuBreadcrumb(Long menuId) {
        List<Menu> breadcrumb = new ArrayList<>();
        Menu currentMenu = menuMapper.selectMenuById(menuId);

        while (currentMenu != null) {
            breadcrumb.add(0, currentMenu);
            if (currentMenu.getParentId() == null || currentMenu.getParentId() == 0) {
                break;
            }
            currentMenu = menuMapper.selectMenuById(currentMenu.getParentId());
        }

        return breadcrumb;
    }

    /**
     * 验证用户是否有菜单权限
     */
    public boolean hasMenuPermission(Long userId, String menuPath) {
        if (userId == null || !StringUtils.hasText(menuPath)) {
            return false;
        }

        List<Menu> userMenus = menuMapper.selectMenusByUserId(userId);
        return userMenus.stream()
                .anyMatch(menu -> menuPath.equals(menu.getMenuPath()));
    }
}
